/*
 * Module 02
 *
 */

package ua.gl.basecamp.tabachnyy.util;

import ua.gl.basecamp.tabachnyy.testcase.Answer;
import ua.gl.basecamp.tabachnyy.testcase.Question;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yaroslav.tabachnyy@gmail.com
 * @version 1.02
 * @date 14.02.2013
 *
 */
public class QuestionsParser {
    private String questionsString;

    public QuestionsParser(String questionsString) {
        this.questionsString = questionsString;
    }

    public List<Question> parseQuestions() {
        Scanner scanner = new Scanner(questionsString);
        List<Question> questions = new ArrayList<Question>();

        while(scanner.hasNextLine()) {
            String questionLine = scanner.nextLine();

            String questionType = parseQuestionType(questionLine);
            Double maxDeviation = null;
            if (questionType.equals("range")) {
                maxDeviation = parseDeviation(questionLine);
            }
            String stringRepresentation = parseStringRepresentation(questionLine);
            List<Answer> answers = parseAnswers(questionLine);

            questions.add(QuestionFactory.createQuestion(questionType,
                    stringRepresentation,
                    answers, maxDeviation));
        }
        return questions;
    }

    private String parseStringRepresentation(String string) {
        final String STRING_REPRESENTATION_PATTERN =
                "(<stringRepresentation>)(.*?)(</stringRepresentation>)";
        final int STRING_GROUP_NUMBER = 2;

        return getFirstOccurrence(string, STRING_REPRESENTATION_PATTERN, STRING_GROUP_NUMBER);
    }

    private String parseQuestionType(String string) {
        final String QUESTION_TYPE_PATTERN =
                "(<question type=\"(.*?)\")";
        final int QUESTION_TYPE_GROUP_NUMBER = 2;

        return getFirstOccurrence(string, QUESTION_TYPE_PATTERN, QUESTION_TYPE_GROUP_NUMBER);
    }

    private List<Answer> parseAnswers(String string) {
        final String ANSWER_PATTERN =
                "(<answer correct=\"(.*?)\">)(.*?)(</answer>)";
        final int CORRECTNESS_GROUP_NUMBER = 2;
        final int ANSWER_TEXT_GROUP_NUMBER = 3;

        Pattern pattern = Pattern.compile(ANSWER_PATTERN);
        Matcher matcher = pattern.matcher(string);

        List<Answer> answers = new ArrayList<Answer>();
        while (matcher.find()) {
            String answerText = matcher.group(ANSWER_TEXT_GROUP_NUMBER);
            boolean isCorrect = Boolean.parseBoolean(matcher.group(CORRECTNESS_GROUP_NUMBER));

            answers.add(new Answer(answerText, isCorrect));
        }

        return answers;
    }

    private double parseDeviation(String string) {
        final String DEVIATION_PATTERN =
                "(<question type=\"(.*?)\" (deviation=\"(.*?)\")?>)";
        final int DEVIATION_GROUP_NUMBER = 4;

        String deviation = getFirstOccurrence(string, DEVIATION_PATTERN, DEVIATION_GROUP_NUMBER);
        return Double.parseDouble(deviation);
    }

    private String getFirstOccurrence(String string, String stringPattern, int groupNumber) {
        Pattern pattern = Pattern.compile(stringPattern);
        Matcher matcher = pattern.matcher(string);

        if (!matcher.find())
            throw new IllegalArgumentException("Illegal string!");

        return matcher.group(groupNumber);
    }
}
